/**
 * Description:
 * Class Name:ServerThread
 * Date:2022/5/24 10:46
 *
 * @author LTisme
 * @version JAVA17
 */
package 疯狂Java讲义.第17章_网络编程._17_3_基于TCP协议的网络编程._17_3_5_记录用户信息;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class ServerThread extends Thread{
    private Socket socket;
    BufferedReader br = null;
    PrintStream ps = null;

    public ServerThread(Socket socket){
        this.socket = socket;
    }

    // 将读到的内容去掉前后协议字符，恢复成真实数据
    private String getRealMsg(String line){
        return line.substring(CrazyItProtocol.PROTOCOL_LEN, line.length() - CrazyItProtocol.PROTOCOL_LEN);
    }

    @Override
    public void run() {
        try {
            // 获取该Socket对应的输入流
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 获取该Socket对应的输出流
            ps = new PrintStream(socket.getOutputStream());
            String line = null;
            while ((line = br.readLine()) != null){
                // 如果读到的行以CrazyItProtocol.USER_ROUND 开始，并以其结束
                // 则可以确定读到的是用户登录的用户名
                if (line.startsWith(CrazyItProtocol.USER_ROUND) && line.endsWith(CrazyItProtocol.USER_ROUND)){
                    // 得到掐头去尾后的真实消息
                    String userName = getRealMsg(line);
                    // 如果用户名重复
                    if (Server.clients.map.containsKey(userName)){
                        System.out.println("用户名重复");
                        ps.println(CrazyItProtocol.NAME_REP);
                    }
                    else {
                        System.out.println("成功");
                        ps.println(CrazyItProtocol.LOGIN_SUCCESS);
                        Server.clients.map.put(userName, ps);
                    }
                }
                // 如果读到的行是以CrazyItProtocol.PRIVATE_ROUND开始，并以其结束
                // 则可以确定是私聊信息，私聊信息只向特定的输出流发送
                else if (line.startsWith(CrazyItProtocol.PRIVATE_ROUND) && line.endsWith(CrazyItProtocol.PRIVATE_ROUND)) {
                    // 得到掐头去尾后的真实消息
                    String userAndMsg = getRealMsg(line);
                    // 以SPlIT_SIGN分割字符串，前半是私聊用户，后半是聊天信息
                    String user = userAndMsg.split(CrazyItProtocol.SPLIT_SIGN)[0];
                    String msg = userAndMsg.split(CrazyItProtocol.SPLIT_SIGN)[1];
                    ///////////////////////////////////////////////////////////////////////////
                    // 获取私聊用户对应的输出流，并发送私聊信息
                    ///////////////////////////////////////////////////////////////////////////
                    Server.clients.map.get(user).println(Server.clients.getKeyByValue(ps) + "悄悄对你说：" + msg);
                }
                // 公聊则是要向每个Socket发送
                else {
                    // 得到掐头去尾后的真实消息
                    String msg = getRealMsg(line);
                    // 遍历clients中的每个输出流
                    for (var clientsPs :
                            Server.clients.valueSet()) {
                        clientsPs.println(Server.clients.getKeyByValue(ps) + "说：" + msg);
                    }
                }
            }
        }
        // 若捕获到异常说明该Socket对应的客户端已经出现了问题
        // 所以程序将其对应的输出流从Map中删除
        catch (IOException e) {
            Server.clients.removeByValue(ps);
            System.out.println(Server.clients.map.size());
            // 关闭网络、IO资源
            try {
                if (br != null){
                    br.close();
                }
                if (ps != null){
                    ps.close();
                }
                if (socket != null){
                    socket.close();
                }
            }
            catch (IOException ex){
                ex.printStackTrace();
            }
        }
    }
}
